/*
 * 文件名： GeneralAlarmStateTag.java
 * 
 * 创建日期： 2016年12月1日
 *
 * Copyright(C) 2016, by <a href="mailto:liws@xingyuanauto.com">liws</a>.
 *
 * 原始作者: liws
 *
 */
package com.moli.iov.protocol.enums.realtime;

import com.moli.iov.protocol.enums.IDictsMultiEnumTag;
import com.moli.iov.util.ByteArrayUtil;

import java.util.HashMap;
import java.util.Map;


/**
 * 通用报警标志位 定义
 *
 * @author <a href="mailto:liws@xingyuanauto.com">liws</a>
 *
 * @version $Revision$
 *
 * @since 2016年12月1日
 */
public class GeneralAlarmStateTag implements IDictsMultiEnumTag{

	 /** 
	 */ 
	private static final long serialVersionUID = 1L;

	//bit位长度
	private static final byte BITS_LEN = 32;
	
	// 二进制bit位 0
	private static final char BIT_0 = '0';


	// 存放单字节4*8 bit位
	private char[] alarmBits;

	public GeneralAlarmStateTag() {
		//初始化bits数组
		alarmBits = new char[BITS_LEN];
		for (int i = 0; i < BITS_LEN; i++) {
			alarmBits[i] = BIT_0;
		}
	}
	
	/**
	 * 设置告警数据 国标暂定为18个状态
	 * 
	 * @param isValid
	 * @param lat
	 * @param lon
	 */
	public void setAlarmInfo(AlarmType alarmType,IsAlarm isAlarm){
		if(alarmType==null)
			return;
		if(isAlarm==null){
			isAlarm = IsAlarm.NO;
		}
		//获取告警信息所在字节数组中的bit位索引
		byte bitIndex = alarmType.getValue();
		//获取是否告警bit位值 1或0(告警或正常)
		char isAlarmBit = isAlarm.getValue();
		//设置对应告警类型对应bit位 数值
		this.alarmBits[(BITS_LEN-1)-bitIndex] = isAlarmBit;
	}
	/**
	 * 获取 根据告警类型 获取是否告警
	 * 
	 * @param aType
	 * @return IsAlarm
	 */
	public IsAlarm getIsAlarm(AlarmType aType){
		return IsAlarm.valOf(this.alarmBits[(BITS_LEN-1)-aType.getValue()]);
	}
	/**
	 * 设置告警数据 国标暂定为18个状态
	 * 
	 */
	public IsAlarm getAlarmInfo(AlarmType alarmType){
		if(alarmType==null)
			return IsAlarm.NO;
		
		//获取告警信息所在字节数组中的bit位索引
		byte bitIndex = alarmType.getValue();
		
		return IsAlarm.valOf(this.alarmBits[(BITS_LEN-1)-bitIndex]);
	}
	/**
	 * 报警类型
	 *
	 * @author <a href="mailto:liws@xingyuanauto.com">liws</a>
	 *
	 * @version $Revision$
	 *
	 * @since 2016年12月1日
	 */
	public enum AlarmType {
		TEMPERATURE_DIFFERENCE("温度差异", (byte) 0),
		BATTERY_HIGH_TEMPERATURE("电池高温", (byte) 1),
		ENERGY_STORING_DEVICE_OVERPRESSURE("车载储能装置类型过压", (byte) 2),
		ENERGY_STORING_DEVICE_UNDERPRESSURE("车载储能装置类型欠压", (byte) 3),
		SOC_LOW("SOC低", (byte) 4),
		SINGLE_BATTERY_OVERPRESSURE("单体电池过压", (byte) 5),
		SINGLE_BATTERY_UNDERPRESSURE("单体电池欠压", (byte) 6),
		SOC_OVER("SOC过高", (byte) 7),
		SOC_LEAPING("SOC跳变", (byte) 8),
		STORAGE_SYSTEMS_NON_MATCHED("可充电储能系统不匹配", (byte) 9),
		BATTERY_SINGLE_CONFORMING_BAD("电池单体一致性差", (byte) 10),
		INSULATION("绝缘", (byte) 11),
		DCDC_TEMPERATURE("DC-DC温度", (byte) 12),
		BRAKE_SYSTEM("制动系统", (byte) 13),
		DCDC_STATE("DC-DC状态", (byte) 14),
		DRIVE_MOTOR_CONTROL_TEMPERATURE("驱动电机控制器温度", (byte) 15),
		HIGH_PRESSURE_INTERLOCK_STATE("高压互锁状态", (byte) 16),
		DRIVE_MOTOR_TEMPERATURE("驱动电机温度", (byte) 17),
		ENERGY_STORING_DEVICE_OVERCHARGE("车载储能装置类型过充", (byte) 18);
		
		private String key;
		private byte value;
		
		public static AlarmType valOf(byte parByte){
			switch (parByte) {
			case 0:
				return TEMPERATURE_DIFFERENCE;
			case 1:
				return BATTERY_HIGH_TEMPERATURE;
			case 2:
				return ENERGY_STORING_DEVICE_OVERPRESSURE;
			case 3:
				return ENERGY_STORING_DEVICE_UNDERPRESSURE;
			case 4:
				return SOC_LOW;
			case 5:
				return SINGLE_BATTERY_OVERPRESSURE;
			case 6:
				return SINGLE_BATTERY_UNDERPRESSURE;
			case 7:
				return SOC_OVER;
			case 8:
				return SOC_LEAPING;
			case 9:
				return STORAGE_SYSTEMS_NON_MATCHED;
			case 10:
				return BATTERY_SINGLE_CONFORMING_BAD;
			case 11:
				return INSULATION;
			case 12:
				return DCDC_TEMPERATURE;
			case 13:
				return BRAKE_SYSTEM;
			case 14:
				return DCDC_STATE;
			case 15:
				return DRIVE_MOTOR_CONTROL_TEMPERATURE;
			case 16:
				return HIGH_PRESSURE_INTERLOCK_STATE;
			case 17:
				return DRIVE_MOTOR_TEMPERATURE;
			case 18:
				return ENERGY_STORING_DEVICE_OVERCHARGE;
			default:
				return null;
			}
		}
		AlarmType(String key, byte value) {
			this.key = key;
			this.value = value;
		}

		public static String getKey(byte value) {
			for (AlarmType c : AlarmType.values()) {
				if (c.getValue() == value) {
					return c.key;
				}
			}
			return null;
		}

		public String getKey() {
			return this.key;
		}

		public byte getValue() {
			return this.value;
		}
	}
	/**
	 * 是否报警
	 *
	 * @author <a href="mailto:liws@xingyuanauto.com">liws</a>
	 *
	 * @version $Revision$
	 *
	 * @since 2016年12月1日
	 */
	public enum IsAlarm {
		NO("未报警", '0'), YES("已报警", '1');
		
		private String key;
		private char value;

		IsAlarm(String key, char value) {
			this.key = key;
			this.value = value;
		}
		public static IsAlarm valOf(char pChar){
			switch (pChar) {
			case '0':
				return NO;
			case '1':
				return YES;
			default:
				return null;
			}
		}
		public static String getKey(char value) {
			for (IsAlarm c : IsAlarm.values()) {
				if (c.getValue()==value) {
					return c.key;
				}
			}
			return NO.getKey();
		}

		public String getKey() {
			return this.key;
		}

		public char getValue() {
			return this.value;
		}
	}

	 /**
	 *
	 */
	@Override
	public String getK() {
		StringBuilder sBuilder = new StringBuilder();
		AlarmType aType = null;
		for(int i =0; i<alarmBits.length;i++){
			aType = AlarmType.valOf((byte)i);
			if(aType==null)
				continue;
			sBuilder.append(aType.getKey()+"告警:"+IsAlarm.valOf(alarmBits[BITS_LEN-i-1])+"\r\n");
		}
		return sBuilder.toString();
	}

	 /**
	 *
	 */
	@Override
	public byte[] getV() {
		byte[] bytes = new byte[4];
		char[] tempBits  = new char[8];
		for(int i = 1;i <= bytes.length;i++){
			System.arraycopy(this.alarmBits, i*8-8, tempBits, 0, tempBits.length);
			bytes[i-1] = ByteArrayUtil.bitToByte(new String(tempBits));
		}
		return bytes;
	}

	/**
	 *
	 * @return
	 */
	public Map<Byte, IsAlarm> getVOfList(){
		Map<Byte, IsAlarm> map = new HashMap<>();

		AlarmType aType = null;
		for(int i =0; i<alarmBits.length;i++){
			aType = AlarmType.valOf((byte)i);
			if(aType==null)
				continue;
			map.put(aType.getValue(), IsAlarm.valOf(alarmBits[BITS_LEN-i-1]));
		}
		return map;
	}
	
	public static void main(String[] args) {
		GeneralAlarmStateTag gAlarm = new GeneralAlarmStateTag();
		//gAlarm.setAlarmInfo(AlarmType.TEMPERATURE_DIFFERENCE, IsAlarm.YES);
		gAlarm.setAlarmInfo(AlarmType.BATTERY_HIGH_TEMPERATURE, IsAlarm.YES);
		//gAlarm.setAlarmInfo(AlarmType.ENERGY_STORING_DEVICE_OVERCHARGE, IsAlarm.YES);
		//gAlarm.setAlarmInfo(AlarmType.SOC_LOW, IsAlarm.YES);
		//gAlarm.setAlarmInfo(AlarmType.SOC_LEAPING, IsAlarm.YES);
		//gAlarm.setAlarmInfo(AlarmType.SOC_OVER, IsAlarm.YES);
		//gAlarm.setAlarmInfo(AlarmType.ENERGY_STORING_DEVICE_OVERCHARGE, IsAlarm.YES);
		byte[] data = gAlarm.getV();
		System.out.println(ByteArrayUtil.toHexString(data));
		System.out.println(gAlarm.getK());
		gAlarm = (GeneralAlarmStateTag)gAlarm.valueOf(data);
		System.out.println(gAlarm.getK());

		Map<Byte, IsAlarm> vOfList = gAlarm.getVOfList();
		vOfList.forEach((key, value) -> {
			System.out.println(key +" : " + value);
		});
	}

	 /**
	 *
	 */
	@Override
	public IDictsMultiEnumTag valueOf(byte[] pByte) {
		StringBuilder sBuilder = new StringBuilder();
		for(int i = 0;i < pByte.length;i++){
			sBuilder.append(ByteArrayUtil.byteToBit(pByte[i]));
		}
		char [] charLocation = sBuilder.toString().toCharArray();
		GeneralAlarmStateTag gAlarm = new GeneralAlarmStateTag();
		gAlarm.setAlarmInfo(AlarmType.TEMPERATURE_DIFFERENCE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.TEMPERATURE_DIFFERENCE.getValue()]));//温度差异报警
		gAlarm.setAlarmInfo(AlarmType.BATTERY_HIGH_TEMPERATURE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.BATTERY_HIGH_TEMPERATURE.getValue()]));//电池高温报警
		gAlarm.setAlarmInfo(AlarmType.ENERGY_STORING_DEVICE_OVERPRESSURE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.ENERGY_STORING_DEVICE_OVERPRESSURE.getValue()]));//车载储能装置类型过压报警
		gAlarm.setAlarmInfo(AlarmType.ENERGY_STORING_DEVICE_UNDERPRESSURE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.ENERGY_STORING_DEVICE_UNDERPRESSURE.getValue()]));//车载储能装置类型欠压报警
		gAlarm.setAlarmInfo(AlarmType.SOC_LOW, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.SOC_LOW.getValue()]));//低soc报
		gAlarm.setAlarmInfo(AlarmType.SINGLE_BATTERY_OVERPRESSURE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.SINGLE_BATTERY_OVERPRESSURE.getValue()]));//单体电池过压报警
		gAlarm.setAlarmInfo(AlarmType.SINGLE_BATTERY_UNDERPRESSURE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.SINGLE_BATTERY_UNDERPRESSURE.getValue()]));//单体电池欠压报警
		gAlarm.setAlarmInfo(AlarmType.SOC_OVER, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.SOC_OVER.getValue()]));//soc过高报警
		gAlarm.setAlarmInfo(AlarmType.SOC_LEAPING,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.SOC_LEAPING.getValue()]));//soc跳变报警
		gAlarm.setAlarmInfo(AlarmType.STORAGE_SYSTEMS_NON_MATCHED,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.STORAGE_SYSTEMS_NON_MATCHED.getValue()]));//可充电储能系统不匹配报警
		gAlarm.setAlarmInfo(AlarmType.BATTERY_SINGLE_CONFORMING_BAD,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.BATTERY_SINGLE_CONFORMING_BAD.getValue()]));//电池单体一致性差报警
		gAlarm.setAlarmInfo(AlarmType.INSULATION,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.INSULATION.getValue()]));//绝缘报警
		gAlarm.setAlarmInfo(AlarmType.DCDC_TEMPERATURE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.DCDC_TEMPERATURE.getValue()]));//DC-DC温度报警
		gAlarm.setAlarmInfo(AlarmType.BRAKE_SYSTEM,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.BRAKE_SYSTEM.getValue()]));//制动系统报警
		gAlarm.setAlarmInfo(AlarmType.DCDC_STATE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.DCDC_STATE.getValue()]));//DC-DC状态报警
		gAlarm.setAlarmInfo(AlarmType.DRIVE_MOTOR_CONTROL_TEMPERATURE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.DRIVE_MOTOR_CONTROL_TEMPERATURE.getValue()]));//驱动电机控制器温度报警
		gAlarm.setAlarmInfo(AlarmType.HIGH_PRESSURE_INTERLOCK_STATE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.HIGH_PRESSURE_INTERLOCK_STATE.getValue()]));//高压互锁状态报警
		gAlarm.setAlarmInfo(AlarmType.DRIVE_MOTOR_TEMPERATURE,IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.DRIVE_MOTOR_TEMPERATURE.getValue()]));//驱动电机温度报警
		gAlarm.setAlarmInfo(AlarmType.ENERGY_STORING_DEVICE_OVERCHARGE, IsAlarm.valOf(charLocation[(BITS_LEN-1)-AlarmType.ENERGY_STORING_DEVICE_OVERCHARGE.getValue()]));//车载储能装置类型过充
		return gAlarm;
	}
	
}
